package com.ray.wms.service.compose;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.ray.common.SysMsgCodeConstant;
import com.ray.validate.support.utils.ValidateUtil;
import com.ray.wms.builder.GoodsBuilder;
import com.ray.wms.builder.OrderInBuilder;
import com.ray.wms.builder.OrderRecordBuilder;
import com.ray.wms.check.OrderInCheck;
import com.ray.wms.check.WarehouseCheck;
import com.ray.wms.enums.InOutTypeEnum;
import com.ray.wms.enums.OrderStatusEnum;
import com.ray.wms.service.*;
import com.ray.wms.table.dto.GoodsDTO;
import com.ray.wms.table.dto.OrderCreateDTO;
import com.ray.wms.table.dto.OrderDTO;
import com.ray.wms.table.dto.OrderStatusChangeDTO;
import com.ray.wms.table.entity.WmsOrderIn;
import com.ray.wms.table.entity.WmsOrderRecord;
import com.ray.wms.table.entity.WmsWarehouse;
import com.ray.woodencreate.beans.LoginUser;
import com.ray.woodencreate.exception.BusinessExceptionFactory;
import com.ray.woodencreate.result.MsgCodeConstant;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author bo shen
 * @Description: 入库集成服务
 * @Class: InService
 * @Package com.ray.wms.service.compose
 * @date 2020/6/3 15:08
 * @company <p>Ray快速开发平台</p>
 * @updateRecord time(修改时间)  author(修改人)   desc(修改内容)
 */
@Service
@Slf4j
public class InService {


    @Autowired
    private WmsOrderRecordService wmsOrderRecordService;
    @Autowired
    private WmsWarehouseStockService wmsWarehouseStockService;
    @Autowired
    private WmsWarehouseStockDetailService wmsWarehouseStockDetailService;
    @Autowired
    private WmsWarehouseStockLogService wmsWarehouseStockLogService;
    @Autowired
    private WmsWarehouseService wmsWarehouseService;
    @Autowired
    private WmsOrderInService wmsOrderInService;

    /**
     * 入库单入库操作
     *
     * @param orderDTO
     * @param loginUser
     * @return
     */
    public boolean orderIn(OrderDTO orderDTO, LoginUser loginUser) {
        //查询订单对应明细数据
        List<WmsOrderRecord> wmsOrderRecords = wmsOrderRecordService.list(orderDTO.getOrderNo(), loginUser);
        if (ObjectUtil.isNotEmpty(wmsOrderRecords)) {
            //进行数据操作
            wmsOrderRecords.forEach(wmsOrderRecord -> {
                GoodsBuilder goodsBuilder = new GoodsBuilder();
                goodsBuilder.append(wmsOrderRecord).appendWarehouseCode(orderDTO.getWarehouseCode()).appendOrderNo(orderDTO.getBusinessOrderNo()).appendInOutType(InOutTypeEnum.IN.getValue());
                if (!wmsWarehouseStockService.addStock(goodsBuilder.bulid(), loginUser)) {
                    log.info("仓库库存更新异常:{}", JSON.toJSONString(goodsBuilder.bulid()));
                    throw BusinessExceptionFactory.newException("仓库库存更新异常");
                }
                if (!wmsWarehouseStockDetailService.addDetail(goodsBuilder.bulid(), loginUser)) {
                    log.info("仓库明细库存更新异常:{}", JSON.toJSONString(goodsBuilder.bulid()));
                    throw BusinessExceptionFactory.newException("仓库明细库存更新异常");
                }
                if (!wmsWarehouseStockLogService.addLog(goodsBuilder.bulid(), loginUser)) {
                    log.info("仓库库存日志更新异常:{}", JSON.toJSONString(goodsBuilder.bulid()));
                    throw BusinessExceptionFactory.newException("仓库库存日志更新异常");
                }
            });
        }
        return true;
    }


    /**
     * 入库单入库操作
     *
     * @param goodsDTO
     * @param loginUser
     * @return
     */
    public boolean orderIn(GoodsDTO goodsDTO, LoginUser loginUser) {
        if (!wmsWarehouseStockService.addStock(goodsDTO, loginUser)) {
            log.info("仓库库存更新异常:{}", JSON.toJSONString(goodsDTO));
            throw BusinessExceptionFactory.newException("仓库库存更新异常");
        }
        if (!wmsWarehouseStockDetailService.addDetail(goodsDTO, loginUser)) {
            log.info("仓库明细库存更新异常:{}", JSON.toJSONString(goodsDTO));
            throw BusinessExceptionFactory.newException("仓库明细库存更新异常");
        }
        if (!wmsWarehouseStockLogService.addLog(goodsDTO, loginUser)) {
            log.info("仓库库存日志更新异常:{}", JSON.toJSONString(goodsDTO));
            throw BusinessExceptionFactory.newException("仓库库存日志更新异常");
        }
        return true;
    }


    /**
     * 入库单取消操作
     *
     * @param orderDTO
     * @param loginUser
     * @return
     */
    public boolean orderCancel(OrderDTO orderDTO, LoginUser loginUser) {
        //查询订单对应明细数据
        List<WmsOrderRecord> wmsOrderRecords = wmsOrderRecordService.list(orderDTO.getOrderNo(), loginUser);
        if (ObjectUtil.isNotEmpty(wmsOrderRecords)) {
            //进行数据操作
            wmsOrderRecords.forEach(wmsOrderRecord -> {
                GoodsBuilder goodsBuilder = new GoodsBuilder();
                goodsBuilder.append(wmsOrderRecord).cancel()
                        .appendWarehouseCode(orderDTO.getWarehouseCode()).appendOrderNo(orderDTO.getBusinessOrderNo()).appendInOutType(InOutTypeEnum.OUT.getValue());
                if (!wmsWarehouseStockService.addStock(goodsBuilder.bulid(), loginUser)) {
                    log.info("仓库库存更新异常:{}", JSON.toJSONString(goodsBuilder.bulid()));
                    throw BusinessExceptionFactory.newException(SysMsgCodeConstant.Error.ERR10000016);
                }
                if (!wmsWarehouseStockDetailService.addDetail(goodsBuilder.bulid(), loginUser)) {
                    log.info("仓库明细库存更新异常:{}", JSON.toJSONString(goodsBuilder.bulid()));
                    throw BusinessExceptionFactory.newException(SysMsgCodeConstant.Error.ERR10000016);
                }
                if (!wmsWarehouseStockLogService.addLog(goodsBuilder.bulid(), loginUser)) {
                    log.info("仓库明细库存更新异常:{}", JSON.toJSONString(goodsBuilder.bulid()));
                    throw BusinessExceptionFactory.newException(SysMsgCodeConstant.Error.ERR10000016);
                }
            });
        }
        return true;
    }


    /**
     * 创建入库订单
     *
     * @return
     */
    public Boolean createOrderIn(OrderCreateDTO createDTO, LoginUser loginUser) {
        ValidateUtil.validate(createDTO);
        WmsWarehouse wmsWarehouse = wmsWarehouseService.queryWarehouseByWarehouseCode(createDTO.getWarehouseCode(), loginUser);
        new WarehouseCheck(wmsWarehouse).checkNull(SysMsgCodeConstant.Error.ERR10000002);

        OrderInBuilder orderInBuilder = new OrderInBuilder();
        orderInBuilder.append(createDTO).appendCreate(loginUser);
        wmsOrderInService.save(orderInBuilder.bulid());
        //商品明细
        List<WmsOrderRecord> wmsOrderRecords = createDTO.getGoodsDTOS().stream().map(goodsDTO -> {
            return new OrderRecordBuilder().append(goodsDTO).appendOrderNo(orderInBuilder.getCode()).appendCreate(loginUser).bulid();
        }).collect(Collectors.toList());
        return wmsOrderRecordService.saveBatch(wmsOrderRecords);
    }


    /**
     * 作废订单
     *
     * @param orderNo
     * @param loginUser
     * @return
     */
    public boolean invalidOrder(String orderNo, LoginUser loginUser) {
        WmsOrderIn orderIn = wmsOrderInService.queryByOrderNo(orderNo, loginUser);
        new OrderInCheck(orderIn).checkNull(SysMsgCodeConstant.Error.ERR10000002).invalidCheck(SysMsgCodeConstant.Error.ERR10000015);
        //更新订单状态
        OrderStatusChangeDTO orderStatusChangeDTO = new OrderStatusChangeDTO(orderNo, OrderStatusEnum.INVALID.getValue(), orderIn.getUpdateVersion());
        if (!wmsOrderInService.updateStatus(orderStatusChangeDTO, loginUser)) {
            log.info("更新订单状态异常,参数：{}", JSON.toJSONString(orderStatusChangeDTO));
            throw BusinessExceptionFactory.newException(MsgCodeConstant.Error.ERR00000001);
        }
        return true;
    }

    /**
     * @param orderNo
     * @param loginUser
     * @return
     */
    public boolean invalidOrderBusinessCode(String orderNo, LoginUser loginUser) {
        List<WmsOrderIn> orderIns = wmsOrderInService.list(orderNo,Arrays.asList(OrderStatusEnum.CANCEL.getValue(),OrderStatusEnum.UN_DO.getValue()), loginUser);
        if(ObjectUtil.isEmpty(orderIns)){
            log.info("无法查询业务单:{},对应的入库单信息.",orderNo);
            throw BusinessExceptionFactory.newException("没有查询到可作废的入库单");
        }
        if (ObjectUtil.isNotEmpty(orderIns)) {
            orderIns.forEach(wmsOrderIn -> {
                invalidOrder(wmsOrderIn.getOrderNo(), loginUser);
            });
        }
        return true;
    }
}
